package com.bioscript.standalone.IO;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.bioscript.standalone.IO.ContigsParsingEvents.ContigParsingEventTypes;
import com.bioscript.standalone.dataStructures.Contig;
import com.bioscript.standalone.dataStructures.Range;

public class FileReader {

	public static List<Range> readProcessedSNPs(String fileName)
	{
		List<Range> range = new ArrayList<Range>();
		try
		{
			ReaderClass<List<Range>> readerClass = new ReaderClass<List<Range>>() {
				@Override
				public void read(String readLine) {
					String[] params = readLine.split("\t");
					Range mappedRange = new Range(Integer.parseInt(params[0]), Integer.parseInt(params[1]), params[2]);
					getValue().add(mappedRange);
				}
			};
			readerClass.setValue(range);
			readerClass.setup(fileName);
			return readerClass.getValue();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	public List<Contig> parseTilingFile(String fileName)
	{
		try
		{
			ReaderClass<List<Contig>> readerClass = new ReaderClass<List<Contig>>() {

				boolean headerRead = false;
				@Override
				public void read(String readLine) {
					if (headerRead)
					{
						String[] params = readLine.split("\t");
						Range mappedRange = new Range(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
						//						Contig contig = new Contig(mappedRange, Integer.parseInt(params[7].split("_")[3]), params[7].split("_length")[0]);
						Contig contig = new Contig(mappedRange, 0, params[7].split("_length")[0]);
						getValue().add(contig);
					}
					else headerRead = true;
				}
			};
			List<Contig> contigs = new ArrayList<Contig>();
			readerClass.setValue(contigs);
			readerClass.setup(fileName);
			return readerClass.getValue();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	public static List<String> readFromFile(String fileName)
	{
		List<String> lst = new ArrayList<String>();
		try
		{
			ReaderClass<List<String>> readerClass = new ReaderClass<List<String>>() {

				@Override
				public void read(String readLine) {
					getValue().add(readLine.trim());
				}
			};
			readerClass.setValue(lst);
			readerClass.setup(fileName);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return lst;
	}


	public List<Range> parseTilingFile2(String fileName)
	{
		try
		{
			ReaderClass<List<Range>> readerClass = new ReaderClass<List<Range>>() {

				boolean headerRead = false;
				@Override
				public void read(String readLine) {
					if (headerRead)
					{
						String[] params = readLine.split("\t");
						Range mappedRange = new Range(Integer.parseInt(params[0]), Integer.parseInt(params[1]), params[7]);
						getValue().add(mappedRange);
					}
					else headerRead = true;
				}
			};
			List<Range> contigs = new ArrayList<Range>();
			readerClass.setValue(contigs);
			readerClass.setup(fileName);
			return readerClass.getValue();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	public static List<String> readFastaHeaders(String fileName)
	{
		ArrayList<String> arrayList = new ArrayList<String>();
		ReaderClass<ArrayList<String>> readerClass = new ReaderClass<ArrayList<String>>() {

			@Override
			public void read(String readLine) {
				if (readLine.startsWith(">"))
				{
					getValue().add(readLine.trim());
				}
			}
		};
		readerClass.setValue(arrayList);
		try
		{
			readerClass.setup(fileName);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return arrayList;
	}

	public ArrayList<Contig> read454Contigs(String fileName)
	{
		ArrayList<Contig> arrayList = new ArrayList<Contig>();
		ReaderClass<ArrayList<Contig>> readerClass = new ReaderClass<ArrayList<Contig>>() {

			@Override
			public void read(String readLine) {
				if (readLine.startsWith(">"))
				{
					String[] params = readLine.replaceAll("\\s+", " ").trim().split(" ");
					Range mappedRange = new Range(Integer.parseInt(params[2].split("\\.\\.")[0]), 
							Integer.parseInt(params[2].split("\\.\\.")[1]));
					Contig contig = new Contig(mappedRange, Integer.parseInt(params[3].split("=")[1]),
							params[1].substring(1));
					getValue().add(contig);
				}
			}
		};
		readerClass.setValue(arrayList);
		try
		{
			readerClass.setup(fileName);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return arrayList;
	}

	public static ArrayList<Contig> readProcessedContigs(String fileName)
	{
		ArrayList<Contig> arrayList = new ArrayList<Contig>();
		ReaderClass<ArrayList<Contig>> readerClass = new ReaderClass<ArrayList<Contig>>() {

			@Override
			public void read(String readLine) {
				if (readLine.startsWith(">"))
				{
					String[] params = readLine.replaceAll("\\s+", " ").trim().split(" ");
					Range mappedRange = new Range(Integer.parseInt(params[1].split("\\.\\.")[0]), 
							Integer.parseInt(params[1].split("\\.\\.")[1]));
					Contig contig = new Contig(mappedRange, Integer.parseInt(params[2].split("=")[1]),
							params[0].substring(1));
					getValue().add(contig);
				}
			}
		};
		readerClass.setValue(arrayList);
		try
		{
			readerClass.setup(fileName);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return arrayList;
	}

	public static List<Contig> readContigsList(String fileName)
	{
		List<Contig> arrayList = new ArrayList<Contig>();
		ReaderClass<List<Contig>> readerClass = new ReaderClass<List<Contig>>() {

			@Override
			public void read(String readLine) {
				if (readLine.startsWith(">"))
				{
					String[] params = readLine.replaceAll("\\s+", " ").trim().split(" ");
					Range mappedRange = new Range(Integer.parseInt(params[2].split("\\.\\.")[0]), 
							Integer.parseInt(params[2].split("\\.\\.")[1]));
					Contig contig = new Contig(mappedRange, Integer.parseInt(params[3].split("=")[1]),
							params[1].substring(1));
					getValue().add(contig);
				}
			}
		};
		readerClass.setValue(arrayList);
		try
		{
			readerClass.setup(fileName);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return arrayList;
	}

	public static List<Range> read454SNPs(String fileName)
	{
		ArrayList<Range> arrayList = new ArrayList<Range>();
		ReaderClass<ArrayList<Range>> readerClass = new ReaderClass<ArrayList<Range>>() {

			@Override
			public void read(String readLine) {
				if (readLine.startsWith(">") && !(readLine.contains("Reference") || readLine.contains("Accno")) )
				{
					String[] params = readLine.replaceAll("\\s+", " ").trim().split(" ");
					Range snpRange = new Range(Integer.parseInt(params[1]), 
							Integer.parseInt(params[2]),params[0].substring(1));
					snpRange.setMetadata(readLine);
					getValue().add(snpRange);
				}
			}
		};
		readerClass.setValue(arrayList);
		try
		{
			readerClass.setup(fileName);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return arrayList;
	}

	public static List<Range> readMummerSNPs(String fileName)
	{
		ArrayList<Range> arrayList = new ArrayList<Range>();
		ReaderClass<ArrayList<Range>> readerClass = new ReaderClass<ArrayList<Range>>() {

			@Override
			public void read(String readLine) {
				String[] params = readLine.split("\t");
				Range snpRange = new Range(Integer.parseInt(params[0]), 
						Integer.parseInt(params[0]),params[0]);
				getValue().add(snpRange);
			}
		};
		readerClass.setValue(arrayList);
		try
		{
			readerClass.setup(fileName);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return arrayList;
	}

	public static Map<String,List<String>> contigsFileReader(String fileName) 
	{
		Map<String,List<String>> map = new HashMap<String, List<String>>();
		ContigsFileParser<Map<String,List<String>>> contigsFileParser = 
			new ContigsFileParser<Map<String,List<String>>>(){
			private String currentContigName = null;
			public void handleEvent(ContigsParsingEvents event) 
			{
				if (event.getEventType() instanceof ContigParsingEventTypes)
				{
					switch((ContigParsingEventTypes) event.getEventType())
					{
					case contigStarted:
						currentContigName = (String)event.getSource();
						List<String> lst = new ArrayList<String>(); 
						getValue().put(currentContigName, lst);
						break;
					case seqread:
						List<String> lt = getValue().get(currentContigName);
						lt.add((String)event.getSource());
						getValue().put(currentContigName, lt);
						break;
					}
				}
			}
		};
		contigsFileParser.setValue(map);
		try
		{
			contigsFileParser.parse(new java.io.FileReader(fileName));
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return map;
	}
}
